package com.maistars.spider.service.template;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.maistars.spider.common.util.JsonUtil;
import com.maistars.spider.service.domain.rule.*;
import com.maistars.spider.service.domain.task.CrawlerTask;

import java.util.ArrayList;
import java.util.List;

/**
 * @author dhr
 * @date 2021/9/28 下午1:33
 */
public class TaskTemplate {

    private JSONObject templateContent;

    public TaskTemplate(JSONObject templateContent) {
        this.templateContent = templateContent;
    }

    public TaskTemplate(String templateContent) {
        this.templateContent = JSONObject.parseObject(templateContent);
    }

    public TaskTemplateResult create() {
        TaskTemplateResult taskTemplateResult = new TaskTemplateResult();

        buildCrawlerTask(taskTemplateResult);

        buildPageRules(taskTemplateResult, templateContent.getJSONArray("pageRules"));
        return taskTemplateResult;
    }

    private void buildCrawlerTask(TaskTemplateResult taskTemplateResult) {
        CrawlerTask crawlerTask = CrawlerTask.builder().taskName(templateContent.getString("taskName"))
                .priority(templateContent.getInteger("priority"))
                .comment(templateContent.getString("comment"))
                .build();
        taskTemplateResult.setCrawlerTask(crawlerTask);
    }

    private void buildPageRules(TaskTemplateResult taskTemplateResult, JSONArray pageRuleObjs) {
        // 种子页面规则
        JSONObject seedPageRuleObj = templateContent.getJSONObject("seedPageRule");
        PageRule seedPageRule = buildPageRule(taskTemplateResult.getCrawlerTask(), null, seedPageRuleObj);
        seedPageRule.setLevel(0);
        taskTemplateResult.getPageRules().add(seedPageRule);

        // 非种子页面规则
        for (int i = 0; i < pageRuleObjs.size(); i++) {
            JSONObject pageRuleObj = pageRuleObjs.getJSONObject(i);
            PageRule pageRule = null;
            pageRule = buildPageRule(taskTemplateResult.getCrawlerTask(), taskTemplateResult.getPageRules().get(i), pageRuleObj);
            pageRule.setLevel(i + 1);
            taskTemplateResult.getPageRules().add(pageRule);

            JSONArray fieldRuleArray = pageRuleObj.getJSONArray("fieldRules");
            if (fieldRuleArray != null) {
                buildFieldRules(taskTemplateResult, pageRule, fieldRuleArray);
            }
        }


    }

    private PageRule buildPageRule(CrawlerTask crawlerTask, PageRule parentPageRule, JSONObject pageRuleObj) {
        PageRule pageRule = PageRule.builder().ruleName(pageRuleObj.getString("ruleName"))
                .pageType(pageRuleObj.getInteger("pageType"))
                .pageContentType(pageRuleObj.getInteger("pageContentType"))
                .crawlerTask(crawlerTask)
                .parentRule(parentPageRule)
                .build();
        return pageRule;
    }

    private List<FieldRule> buildFieldRules(TaskTemplateResult taskTemplateResult, PageRule pageRule, JSONArray fieldRuleArrayObj) {
        List<FieldRule> fieldRules = new ArrayList<>();
        for (int i = 0; i < fieldRuleArrayObj.size(); i++) {
            JSONObject fieldRuleObj = fieldRuleArrayObj.getJSONObject(i);
            if (!taskTemplateResult.getFieldRules().containsKey(pageRule)) {
                taskTemplateResult.getFieldRules().put(pageRule, new ArrayList<>());
            }
            taskTemplateResult.getFieldRules().get(pageRule).add(buildFieldRule(pageRule, fieldRuleObj));
        }
        return fieldRules;
    }

    private FieldRule buildFieldRule(PageRule pageRule, JSONObject fieldRuleObj) {
        FieldRule fieldRule = FieldRule.builder()
                .rule(fieldRuleObj.getString("rule"))
                .parseType(fieldRuleObj.getInteger("parseType"))
                .fieldName(fieldRuleObj.getString("fieldName"))
                .crawlerTask(pageRule.getCrawlerTask())
                .processConfig(fieldRuleObj.getString("processConfig"))
                .build();
        return fieldRule;
    }

    private UrlRule buildUrlRule(JSONObject urlRuleObj) {
        if (0 == urlRuleObj.getInteger("ruleType")) {
            ParamUrlRule paramUrlRule = ParamUrlRule.builder().paramType(urlRuleObj.getInteger("paramType"))
                    .urlPattern(urlRuleObj.getString("urlPattern"))
                    .build();
            JSONObject params = urlRuleObj.getJSONObject("params");
            if (params != null) {
                paramUrlRule.getParams().putAll(JsonUtil.JsonObjectToHashMap(params));
            }
            return paramUrlRule;
        } else if (1 == urlRuleObj.getInteger("ruleType")) {
            PatternUrlRule patternUrlRule = PatternUrlRule.builder()
                    .urlPattern(urlRuleObj.getString("urlPattern"))
                    .patternType(urlRuleObj.getInteger("patternType"))
                    .fillHead(urlRuleObj.getString("fillHead"))
                    .fillTail(urlRuleObj.getString("fillTail"))
                    .build();
            JSONObject params = urlRuleObj.getJSONObject("params");
            if (params != null) {
                patternUrlRule.getParams().putAll(JsonUtil.JsonObjectToHashMap(params));
            }
            return patternUrlRule;
        }
        return null;
    }

    public static void main(String[] args) {
        String content = "{\"taskName\":\"T-1001\",\"comment\":\"第一个爬虫任务\",\"priority\":0,\"seedPageRule\":{\"ruleName\":\"种子页面识别\",\"pageType\":1,\"urlRule\":{\"ruleType\":0,\"paramType\":1,\"urlPattern\":\"http://www.mybu.net/link.asp\"}},\"pageRules\":[{\"ruleName\":\"第一层页面识别\",\"pageType\":1,\"urlRule\":{\"ruleType\":1,\"patternType\":1,\"fillHead\":\"http://www.mybu.net/\",\"urlPattern\":\"/html/body/div/center/table/tbody/tr/td/table/tbody/tr/td/div/center/table/tbody/tr/td/a/@href\"},\"fieldRules\":[{\"fieldName\":\"urls\",\"parseType\":1,\"rule\":\"/html/body/div[1]/center[1]/table[2]/tbody[1]/tr[1]/td[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/center[1]/table[1]/tbody[1]/tr[4]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/p[1]/a[1]/@href\"}]}]}";
        TaskTemplate taskTemplate = new TaskTemplate(content);
        TaskTemplateResult taskTemplateResult = taskTemplate.create();
        System.out.println(content);
    }

}
